/************************************************************************

								Heroes IV
					  Copyright 2000, The 3DO Company

	------------------------------------------------------------------
  						       abstract_town.h

	$Header: /game/abstract_town.h $

	$NoKeywords: $

 ************************************************************************/

#ifndef ABSTRACT_TOWN_H_INCLUDED
#define ABSTRACT_TOWN_H_INCLUDED

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000

#include "abstract_grail_data_source.h"
#include "abstract_script_action_ptr.h"
#include "creature_array.h"
#include "hero_set.h"
#include "ownable_event_list.h"
#include "owned_adv_object.h"
#include "town_building.h"
#include "scriptable_event.h"
#include "town_building_set.h"

enum t_ai_importance;
enum t_town_type;
enum t_town_image_level;
class t_skill_set;

// -------------------------------------------------------------
// abstract base class for t_town and t_random_town
// -------------------------------------------------------------

class t_abstract_town : public t_owned_adv_object, public t_creature_array, public t_abstract_grail_data_source
{
public:
	typedef t_town_scriptable_event t_built_in_event_id;

	enum { k_built_in_event_count = k_town_scriptable_event_count };

	t_abstract_town( std::string const & model_name );
	virtual ~t_abstract_town();

	void						add_hero_to_nobility_list(t_hero *hero);
	void						destroy();
	t_ai_importance				get_ai_importance() const;
	virtual std::string			get_balloon_help() const;
	t_hero*						get_best_nobility_hero() const;
	t_town_building_set const&	get_buildings() const;
	virtual t_town_image_level	get_castle_level() const;
	t_creature_array&			get_garrison();
	t_creature_array const&		get_garrison() const;
	virtual t_abstract_grail_data_source const & get_grail_data() const;
	int							get_highest_nobility_priority() const;
	int							get_lowest_nobility_priority() const;
	virtual std::string			get_name() const;
	int							get_nobility_bonus() const;
	t_town_type					get_type() const;
	virtual bool				gets_global_grail_effects( t_town_type alignment ) const;
	int							get_towndwelling_count() const;
	bool						has( t_town_building ) const;
	virtual void				initialize( t_adventure_map& map );
	virtual bool				is_deleted_by_deletion_marker() const;
	bool						is_hero_in_nobility_list( t_hero * hero ) const;
	bool						is_legal( t_town_building ) const;
	virtual void				on_adventure_map_destruction();
	virtual bool				preplacement( t_adventure_map& map, int pass );
	virtual bool				read( std::streambuf&					 stream, 
								      t_qualified_adv_object_type const& type,
								      int								 version );
	virtual void				read_postplacement( t_adventure_map& map );
	void						remove_hero_from_nobility_list(t_hero *hero);
	virtual void				set_owner( int player_number );
	virtual bool				write( std::streambuf& stream ) const;

protected:
	explicit t_abstract_town( t_abstract_town* source ); // transfers information from source

	void		clear_nobility_heroes(void);
	virtual int	compute_scouting_range() const;

	bool read_map_data( std::streambuf& buffer, t_progress_handler* handler,
		                bool& custom_garrison, bool& custom_buildings,
						bool & customized_school_skills, t_skill_set & available_school_skills, t_skill_set & required_school_skills);
	bool read_map_data( std::streambuf& buffer, t_progress_handler* handler,
		                bool& custom_garrison, bool& custom_buildings,
						bool & customized_school_skills, t_skill_set & available_school_skills, t_skill_set & required_school_skills,
						int version );
	void post_change();

	typedef t_ownable_built_in_event			t_built_in_event;
	typedef t_ownable_built_in_event_ptr		t_built_in_event_ptr;
	typedef t_ownable_timed_event				t_timed_event;
	typedef t_ownable_timed_event_ptr			t_timed_event_ptr;
	typedef t_ownable_timed_event_list			t_timed_event_list;
	typedef t_ownable_triggerable_event			t_triggerable_event;
	typedef t_ownable_triggerable_event_ptr		t_triggerable_event_ptr;
	typedef t_ownable_triggerable_event_list	t_triggerable_event_list;
	typedef t_ownable_continuous_event			t_continuous_event;
	typedef t_ownable_continuous_event_ptr		t_continuous_event_ptr;
	typedef t_ownable_continuous_event_list		t_continuous_event_list;

	t_ai_importance					m_ai_importance;
	t_town_building_set				m_buildings;
	t_built_in_event_ptr			m_built_in_events[ k_built_in_event_count ];
	t_continuous_event_list			m_continuous_events;
	t_town_building_set				m_enabled_buildings;
	std::string						m_name;
	bool							m_named_by_map;
	t_hero_set_uncounted			m_nobility_heroes; // Heroes which could contribute a nobility bonus to this town. Uncounted to avoid circular references
	t_timed_event_list				m_timed_events;
	t_triggerable_event_list		m_triggerable_events;
	t_town_type						m_type;


private:
	bool read_ai_importance_from_map( std::streambuf & stream, int version );
	bool read_buildings_from_map( std::streambuf & stream, int version, bool & custom_buildings );
	bool read_built_in_events_from_map( std::streambuf & stream, int version );
	bool read_continuous_events_from_map( std::streambuf & stream, int version );
	bool read_events( std::streambuf& stream, int version );
	bool read_garrison_from_map( std::streambuf & stream, int version, bool & custom_garrison );
	bool read_name_from_map( std::streambuf & stream, int version );
	bool read_player_color_from_map( std::streambuf & stream, int version );
	bool read_school_skills_from_map( std::streambuf & stream, int version, bool & customized_school_skills, t_skill_set & available_school_skills, t_skill_set & required_school_skills );
	bool read_timed_events_from_map( std::streambuf & stream, int version );
	bool read_triggerable_events_from_map( std::streambuf & stream, int version );
	bool write_events( std::streambuf& stream ) const;
};

bool is_legal( t_town_type town, t_town_building building );

inline t_ai_importance t_abstract_town::get_ai_importance() const
{
	return m_ai_importance;
}

inline t_town_type t_abstract_town::get_type() const
{
	return m_type;
}

inline bool t_abstract_town::has( t_town_building building ) const
{
	return m_buildings[building];
}

inline bool	t_abstract_town::is_hero_in_nobility_list( t_hero * hero ) const
{
	return m_nobility_heroes.find(hero) != m_nobility_heroes.end();
}

inline bool t_abstract_town::is_legal( t_town_building building ) const
{
	return ::is_legal( m_type, building );
}

inline t_town_building_set const& t_abstract_town::get_buildings() const
{
	return m_buildings;
}

inline t_creature_array& t_abstract_town::get_garrison() 
{
	return *this;
}

inline t_creature_array const& t_abstract_town::get_garrison() const
{
	return *this;
}

#endif // ABSTRACT_TOWN_H_INCLUDED
